什么是RMQ问题?
RMQ(Range Min/Max Query):
对于长度为n的数组A,回答若干询问RMQ(A,i,j)(i,j<=n-1)
返回数组A中下标在i,j范围内的最小(大)值,即RMQ问题是指求区间最值的问题。
解决方式:
- 朴素算法:每查询一次为O(n)
- ST算法:高效,以O(n log n)的预处理代价,换取O(1)的查询时性能
ST算法
令:f[i,j]代表从第i个数起连续2^j个数中的最大值(因此要用倍增)
从下图可以看出:f[0][1]=max(f[0][0],f[1][0]), …… f[[0][2]=max(f[0][1],f[2][1]) ……
采用动态规划的思想:显然f[i,j]=max(f[i,j-1],f[i+2^(j-1),j-1])
所以,我们需要建立ST表,也就是上文中的f数组。生成ST表是一次预处理,此后都是O(1)的查询了。
建立ST表
for(int i=0; i<=n; i++) f[i][0]=a[i]; //初始化,第0列(j=0)就是a[i]。 |
查询时,只需取在ST表中找2段头尾满足区间范围进行拼凑,有重叠覆盖不影响结果。
Why?我们来模拟一下:
设A=2,6,4,8,4,8,4,8 |
查询
设:范围是 [m,n] ,这个范围不会是刚好2 ^k的长度,我们就用2段区间来拼凑:
即[m,m+2^k-1]
和[n-2^k+1,n]
(拼凑后头尾满足[m,n],中间允许重叠)
因此查询结果即为:RMQ[A,m,n]=max(f[m][k],f[n-(1<<k)+1][k]);
其中2^k<=(n-m+1) 则 k=log2(n-m+1);
举个例子:查询RMQ[A,1,6]=max(f[1][2],f[3][2])
log对数函数
这里的log来说一下,对数是对求幂的逆运算,正如除法是乘法的倒数
如果a^x =N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=loga N,读作以a为底N的对数,其中a叫做对数的底数,N叫做真数。
比如说2^5=32,log2 32=5,求的是n次方
ST表例题
【模板】ST表-Luogu
|
质量检测-Luogu
//裸的模版题,只不过是没有询问需要自己“手动添加”罢了 |